<!DOCTYPE html>
<html lang="en-us">
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    
<meta charset="UTF-8">
<title>Indexing Performance Tips | Elasticsearch: The Definitive Guide [2.x] | Elastic</title>
<link rel="home" href="index.html" title="Elasticsearch: The Definitive Guide [2.x]">
<link rel="up" href="post_deploy.html" title="Post-Deployment">
<link rel="prev" href="logging.html" title="Logging">
<link rel="next" href="_delaying_shard_allocation.html" title="Delaying Shard Allocation">
<meta name="DC.type" content="Learn/Docs/Legacy/Elasticsearch/Definitive Guide/2.x">
<meta name="DC.subject" content="Elasticsearch">
<meta name="DC.identifier" content="2.x">
<meta name="robots" content="noindex,nofollow">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.optimizely.com/js/18132920325.js"></script>
    <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
    <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
    <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
    <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
    <link rel="manifest" href="/manifest.json">
    <meta name="apple-mobile-web-app-title" content="Elastic">
    <meta name="application-name" content="Elastic">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="/mstile-144x144.png">
    <meta name="theme-color" content="#ffffff">
    <meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd">
    <meta name="yandex-verification" content="d8a47e95d0972434">
    <meta name="localized" content="true">
    <meta name="st:robots" content="follow,index">
    <meta property="og:image" content="https://www.elastic.co/static/images/elastic-logo-200.png">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <link rel="icon" href="/favicon.ico" type="image/x-icon">
    <link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
    <link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
    <link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" type="text/css" href="/guide/static/styles.css">
  </head>

  <!--© 2015-2021 Elasticsearch B.V. Copying, publishing and/or distributing without written permission is strictly prohibited.-->

  <body>
    <!-- Google Tag Manager -->
    <script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
    <!-- End Google Tag Manager -->

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-12395217-16');
    </script>

    <!--BEGIN QUALTRICS WEBSITE FEEDBACK SNIPPET-->
    <script type="text/javascript">
      (function(){var g=function(e,h,f,g){
      this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null};
      this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "};
      this.check=function(){var a=this.get(f);if(a)a=a.split(":");else if(100!=e)"v"==h&&(e=Math.random()>=e/100?0:100),a=[h,e,0],this.set(f,a.join(":"));else return!0;var c=a[1];if(100==c)return!0;switch(a[0]){case "v":return!1;case "r":return c=a[2]%Math.floor(100/c),a[2]++,this.set(f,a.join(":")),!c}return!0};
      this.go=function(){if(this.check()){var a=document.createElement("script");a.type="text/javascript";a.src=g;document.body&&document.body.appendChild(a)}};
      this.start=function(){var a=this;window.addEventListener?window.addEventListener("load",function(){a.go()},!1):window.attachEvent&&window.attachEvent("onload",function(){a.go()})}};
      try{(new g(100,"r","QSI_S_ZN_emkP0oSe9Qrn7kF","https://znemkp0ose9qrn7kf-elastic.siteintercept.qualtrics.com/WRSiteInterceptEngine/?Q_ZID=ZN_emkP0oSe9Qrn7kF")).start()}catch(i){}})();
    </script><div id="ZN_emkP0oSe9Qrn7kF"><!--DO NOT REMOVE-CONTENTS PLACED HERE--></div>
    <!--END WEBSITE FEEDBACK SNIPPET-->

    <div id="elastic-nav" style="display:none;"></div>
    <script src="https://www.elastic.co/elastic-nav.js"></script>

    <!-- Subnav -->
    <div>
      <div>
        <div class="tertiary-nav d-none d-md-block">
          <div class="container">
            <div class="p-t-b-15 d-flex justify-content-between nav-container">
              <div class="breadcrum-wrapper"><span><a href="/guide/" style="font-size: 14px; font-weight: 600; color: #000;">Docs</a></span></div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="main-container">
      <section id="content">
        <div class="content-wrapper">

          <section id="guide" lang="en">
            <div class="container">
              <div class="row">
                <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                  <!-- start body -->
                  <div class="page_header">
<p>
  <strong>WARNING</strong>: The 2.x versions of Elasticsearch have passed their
  <a href="https://www.elastic.co/support/eol">EOL dates</a>. If you are running
  a 2.x version, we strongly advise you to upgrade.
</p>
<p>
  This documentation is no longer maintained and may be removed. For the latest
  information, see the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">current
  Elasticsearch documentation</a>.
</p>
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch: The Definitive Guide [2.x]</a></span>
»
<span class="breadcrumb-link"><a href="administration.html">Administration, Monitoring, and Deployment</a></span>
»
<span class="breadcrumb-link"><a href="post_deploy.html">Post-Deployment</a></span>
»
<span class="breadcrumb-node">Indexing Performance Tips</span>
</div>
<div class="navheader">
<span class="prev">
<a href="logging.html">« Logging</a>
</span>
<span class="next">
<a href="_delaying_shard_allocation.html">Delaying Shard Allocation »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="indexing-performance"></a>Indexing Performance Tips<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/520_Post_Deployment/30_indexing_perf.asciidoc">edit</a>
</h2>
</div></div></div>
<p>If you are in an indexing-heavy environment, such as indexing infrastructure
logs, you may be willing to sacrifice some search performance for faster indexing
rates.  In these scenarios, searches tend to be relatively rare and performed
by people internal to your organization.  They are willing to wait several
seconds for a search, as opposed to a consumer facing a search that must
return in milliseconds.</p>
<p>Because of this unique position, certain trade-offs can be made
that will increase your indexing performance.</p>
<div class="sidebar">
<div class="titlepage"><div><div>
<p class="title"><strong>These Tips Apply Only to Elasticsearch 1.3+</strong></p>
</div></div></div>
<p>This book is written for the most recent versions of Elasticsearch, although much
of the content works on older versions.</p>
<p>The tips presented in this section, however, are <em>explicitly</em> for version 1.3+.  There
have been multiple performance improvements and bugs fixed that directly impact
indexing.  In fact, some of these recommendations will <em>reduce</em> performance on
older versions because of the presence of bugs or performance defects.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_test_performance_scientifically"></a>Test Performance Scientifically<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/520_Post_Deployment/30_indexing_perf.asciidoc">edit</a>
</h3>
</div></div></div>
<p>Performance testing is always difficult, so try to be as scientific as possible
in your approach.  Randomly fiddling with knobs and turning on ingestion is not
a good way to tune performance.  If there are too many <em>causes</em>, it is impossible
to determine which one had the best <em>effect</em>. A reasonable approach to testing is as follows:</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
Test performance on a single node, with a single shard and no replicas.
</li>
<li class="listitem">
Record performance under 100% default settings so that you have a baseline to
measure against.
</li>
<li class="listitem">
Make sure performance tests run for a long time (30+ minutes) so you can
evaluate long-term performance, not short-term spikes or latencies.  Some events
(such as segment merging, and GCs) won’t happen right away, so the performance
profile can change over time.
</li>
<li class="listitem">
Begin making single changes to the baseline defaults.  Test these rigorously,
and if performance improvement is acceptable, keep the setting and move on to the
next one.
</li>
</ol>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_using_and_sizing_bulk_requests"></a>Using and Sizing Bulk Requests<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/520_Post_Deployment/30_indexing_perf.asciidoc">edit</a>
</h3>
</div></div></div>
<p>This should be fairly obvious, but use bulk indexing requests for optimal performance.
Bulk sizing is dependent on your data, analysis, and cluster configuration, but
a good starting point is 5–15 MB per bulk.  Note that this is physical size.
Document count is not a good metric for bulk size.  For example, if you are
indexing 1,000 documents per bulk, keep the following in mind:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
1,000 documents at 1 KB each is 1 MB.
</li>
<li class="listitem">
1,000 documents at 100 KB each is 100 MB.
</li>
</ul>
</div>
<p>Those are drastically different bulk sizes.  Bulks need to be loaded into memory
at the coordinating node, so it is the physical size of the bulk that is more
important than the document count.</p>
<p>Start with a bulk size around 5–15 MB and slowly increase it until you do not
see performance gains anymore.  Then start increasing the concurrency of your
bulk ingestion (multiple threads, and so forth).</p>
<p>Monitor your nodes with Marvel and/or tools such as <code class="literal">iostat</code>, <code class="literal">top</code>, and <code class="literal">ps</code> to see
when resources start to bottleneck.  If you start to receive <code class="literal">EsRejectedExecutionException</code>,
your cluster can no longer keep up: at least one resource has reached capacity. Either reduce concurrency, provide more of the limited resource (such as switching from spinning disks to SSDs), or add more nodes.</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>When ingesting data, make sure bulk requests are round-robined across all your
data nodes.  Do not send all requests to a single node, since that single node
will need to store all the bulks in memory while processing.</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_storage"></a>Storage<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/520_Post_Deployment/30_indexing_perf.asciidoc">edit</a>
</h3>
</div></div></div>
<p>Disks are usually the bottleneck of any modern server.  Elasticsearch heavily uses disks, and the more throughput your disks can handle, the more stable your nodes will be. Here are some tips for optimizing disk I/O:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
Use SSDs.  As mentioned elsewhere, they are superior to spinning media.
</li>
<li class="listitem">
Use RAID 0.  Striped RAID will increase disk I/O, at the obvious expense of
potential failure if a drive dies.  Don’t use mirrored or parity RAIDS since
replicas provide that functionality.
</li>
<li class="listitem">
Alternatively, use multiple drives and allow Elasticsearch to stripe data across
them via multiple <code class="literal">path.data</code> directories.
</li>
<li class="listitem">
Do not use remote-mounted storage, such as NFS or SMB/CIFS.  The latency introduced
here is antithetical to performance.
</li>
<li class="listitem">
If you are on EC2, beware of EBS.  Even the SSD-backed EBS options are often slower
than local instance storage.
</li>
</ul>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="segments-and-merging"></a>Segments and Merging<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/520_Post_Deployment/30_indexing_perf.asciidoc">edit</a>
</h3>
</div></div></div>
<p>Segment merging is computationally expensive, and can eat up a lot of disk I/O.
Merges are scheduled to operate in the background because they can take a long
time to finish, especially large segments.  This is normally fine, because the
rate of large segment merges is relatively rare.</p>
<p>But sometimes merging falls behind the ingestion rate.  If this happens, Elasticsearch
will automatically throttle indexing requests to a single thread.  This prevents
a <em>segment explosion</em> problem, in which hundreds of segments are generated before
they can be merged. Elasticsearch will log <code class="literal">INFO</code>-level messages stating <code class="literal">now
throttling indexing</code> when it detects merging falling behind indexing.</p>
<p>Elasticsearch defaults here are conservative: you don’t want search performance
to be impacted by background merging.  But sometimes (especially on SSD, or logging
scenarios), the throttle limit is too low.</p>
<p>The default is 20 MB/s, which is a good setting for spinning disks.  If you have
SSDs, you might consider increasing this to 100–200 MB/s.  Test to see what works
for your system:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">PUT /_cluster/settings
{
    "persistent" : {
        "indices.store.throttle.max_bytes_per_sec" : "100mb"
    }
}</pre>
</div>
<p>If you are doing a bulk import and don’t care about search at all, you can disable
merge throttling entirely.  This will allow indexing to run as fast as your
disks will allow:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">PUT /_cluster/settings
{
    "transient" : {
        "indices.store.throttle.type" : "none" <a id="CO308-1"></a><i class="conum" data-value="1"></i>
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO308-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>Setting the throttle type to <code class="literal">none</code> disables merge throttling entirely.  When
you are done importing, set it back to <code class="literal">merge</code> to reenable throttling.</p>
</td>
</tr>
</table>
</div>
<p>If you are using spinning media instead of SSD, you need to add this to your
<code class="literal">elasticsearch.yml</code>:</p>
<div class="pre_wrapper lang-yaml">
<pre class="programlisting prettyprint lang-yaml">index.merge.scheduler.max_thread_count: 1</pre>
</div>
<p>Spinning media has a harder time with concurrent I/O, so we need to decrease
the number of threads that can concurrently access the disk per index.  This setting
will allow <code class="literal">max_thread_count + 2</code> threads to operate on the disk at one time,
so a setting of <code class="literal">1</code> will allow three threads.</p>
<p>For SSDs, you can ignore this setting.  The default is
<code class="literal">Math.min(3, Runtime.getRuntime().availableProcessors() / 2)</code>, which works well
for SSD.</p>
<p>Finally, you can increase <code class="literal">index.translog.flush_threshold_size</code> from the default
512 MB to something larger, such as 1 GB.  This allows larger segments to accumulate
in the translog before a flush occurs.  By letting larger segments build, you
flush less often, and the larger segments merge less often.  All of this adds up
to less disk I/O overhead and better indexing rates.  Of course, you will need
the corresponding amount of heap memory free to accumulate the extra buffering
space, so keep that in mind when adjusting this setting.</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_other"></a>Other<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/520_Post_Deployment/30_indexing_perf.asciidoc">edit</a>
</h3>
</div></div></div>
<p>Finally, there are some other considerations to keep in mind:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
If you don’t need near real-time accuracy on your search results, consider
dropping the <code class="literal">index.refresh_interval</code> of each index to <code class="literal">30s</code>.  If you are doing
a large import, you can disable refreshes by setting this value to <code class="literal">-1</code> for the
duration of the import.  Don’t forget to reenable it when you are finished!
</li>
<li class="listitem">
<p>If you are doing a large bulk import, consider disabling replicas by setting
<code class="literal">index.number_of_replicas: 0</code>.  When documents are replicated, the entire document
is sent to the replica node and the indexing process is repeated verbatim.  This
means each replica will perform the analysis, indexing, and potentially merging
process.</p>
<p>In contrast, if you index with zero replicas and then enable replicas when ingestion
is finished, the recovery process is essentially a byte-for-byte network transfer.
This is much more efficient than duplicating the indexing process.</p>
</li>
<li class="listitem">
If you don’t have a natural ID for each document, use Elasticsearch’s auto-ID
functionality.  It is optimized to avoid version lookups, since the autogenerated
ID is unique.
</li>
<li class="listitem">
If you are using your own ID, try to pick an ID that is <a href="http://blog.mikemccandless.com/2014/05/choosing-fast-unique-identifier-uuid.html" class="ulink" target="_top">friendly to Lucene</a>.  Examples include zero-padded
sequential IDs, UUID-1, and nanotime; these IDs have consistent, sequential
patterns that compress well.  In contrast, IDs such as UUID-4 are essentially
random, which offer poor compression and slow down Lucene.
</li>
</ul>
</div>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="logging.html">« Logging</a>
</span>
<span class="next">
<a href="_delaying_shard_allocation.html">Delaying Shard Allocation »</a>
</span>
</div>
</div>

                  <!-- end body -->
                </div>
                <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                  <div id="rtpcontainer" style="display: block;">
                    <div class="mktg-promo">
                      <h3>Most Popular</h3>
                      <ul class="icons">
                        <li class="icon-elasticsearch-white"><a href="https://www.elastic.co/webinars/getting-started-elasticsearch?baymax=default&amp;elektra=docs&amp;storm=top-video">Get Started with Elasticsearch: Video</a></li>
                        <li class="icon-kibana-white"><a href="https://www.elastic.co/webinars/getting-started-kibana?baymax=default&amp;elektra=docs&amp;storm=top-video">Intro to Kibana: Video</a></li>
                        <li class="icon-logstash-white"><a href="https://www.elastic.co/webinars/introduction-elk-stack?baymax=default&amp;elektra=docs&amp;storm=top-video">ELK for Logs &amp; Metrics: Video</a></li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </section>

        </div>


<div id="elastic-footer"></div>
<script src="https://www.elastic.co/elastic-footer.js"></script>
<!-- Footer Section end-->

      </section>
    </div>

<script src="/guide/static/jquery.js"></script>
<script type="text/javascript" src="/guide/static/docs.js"></script>
<script type="text/javascript">
  window.initial_state = {}</script>
  </body>
</html>
